<?php
/**
 * Created by PhpStorm.
 * User: Rain
 * Date: 2019/11/27
 * Time: 10:05
 */

namespace app\service\alone\Encryption;

use app\admin\service\BaseService;
use app\service\interfaces\EncryptionInterface;

class EncryptionService extends BaseService implements EncryptionInterface
{
    /**
     * 数据加密
     *
     * @param string $string
     * @param string $key
     * @param int $time 时效性 0 永久
     * @return string
     * @throws \Exception
     */
    public function encryption(string $string, string $key = '', int $time = 0): string
    {
        // 验证key的时候，是否准备
        $key = $key ?: sha1(config('app.key'));

        // 加密
        $real = openssl_encrypt(json_encode(['content' => $string, 'time' => $time ? time() + $time : 0]), 'DES-ECB', $key, 0);

        // 随机字符串的长度
        $len = intdiv(strlen($real), 4);

        // 随机字符串，掩饰真实加密数据
        $rand = base64_encode(random_bytes($len));

        // 随机字符串的长度，加密，12位
        $encryption = base64_encode(base64_encode(random_bytes(8)) . strlen($rand));

        // 处理加密数据
        list($str, $num) = ['', 0];
        for ($i = 0; $i < strlen($real); $i++) {
            $str .= $real[$i];

            if (isset($rand[$num])) $str .= $rand[$num++];
        }

        return base64_encode($str . '.' . $encryption);
    }

    /**
     * 解密
     *
     * @param string $encryption
     * @param string $key
     * @return string
     */
    public function decrypt(string $encryption, string $key = ''): string
    {
        // 验证key的时候，是否准备
        $key = $key ?: sha1(config('app.key'));

        try {
            $encryption = explode('.', base64_decode($encryption));

            $randLen = substr(base64_decode($encryption[1]), 12);

            list($str, $n) = ['', 0];
            for ($i = 0; $i < strlen($encryption[0]); $i++) {
                $str .= $encryption[0][$i];

                if ($n < $randLen) $i++;

                $n++;
            }

            // 解密
            if (!$result = openssl_decrypt($str, 'DES-ECB', $key, 0)) return '';

            // 验证时效性
            $data = json_decode($result, true);
            if ($data['time'] !== 0 && time() >= $data['time']) return '';

            return $data['content'];
        } catch (\Exception $exception) {
            return '';
        }
    }
}
